package de.doegel.common.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Pair;
import de.doegel.common.model.AbstractMessage;
import de.doegel.common.model.Contact;
import de.doegel.common.model.News;

public abstract class AbstractHttpConnector {
	public static enum SendMessageResponse {
		SUCCESSFUL, ERROR_NOT_PREMIUM_MEMBER, ERROR_INVALID_ACCOUNT, ERROR_NETWORK_ERROR
	};
	
	public abstract List<AbstractMessage> fetchMessages(Context context, boolean inbox, int offset);
	public abstract AbstractMessage createMessage(boolean inbox, JSONObject json);
	public abstract SendMessageResponse sendMessage(Context context, int personId, String subject, String content);
	public abstract boolean deleteMessage(Context context, int messageID);
	public abstract boolean setMessageAsRead(Context context, int messageID);
	public abstract Pair<Boolean, Integer> login(Context context, String username, String password, String registrationId);
	public abstract boolean logout(Context context, String registrationId);
	public abstract List<Contact> searchContacts(Context context, String searchString, int offset);
	public abstract int fetchTotalContact(Context context);
	public abstract List<Contact> fetchContacts(Context context, int offset);
	public abstract List<News> fetchNews(Context context, int offset);
	
	public abstract Pair<Integer, Integer> fetchAnimalImageAndVideoCounts(Context context, int animalId);
	public abstract String createFetchAnimalImageURL(Context context, int animalId, int offset);
	public abstract String fetchAnimalImageURL(Context context, int animalId, int offset);
	public abstract String createFetchAnimalVideoURL(Context context, int animalId, int offset);
	public abstract String fetchAnimalVideoURL(Context context, int animalId, int offset);
	
	public static String httpGET(String url) throws ClientProtocolException, IOException {
		HttpClient httpClient = createHttpClient();
		HttpResponse response = httpClient.execute(new HttpGet(url));
		return processEntity(response.getEntity());
	}

	public static String httpPOST(String url, List<NameValuePair> nameValuePairs) throws ClientProtocolException, IOException {
		HttpClient httpClient = createHttpClient();
		HttpPost httpPost = new HttpPost(url);
		UrlEncodedFormEntity encodedFormEntity = new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8);
		httpPost.setEntity(encodedFormEntity);
		HttpResponse response = httpClient.execute(httpPost);
		return processEntity(response.getEntity());
	}

	public static String httpPUT(String url, String data) throws ClientProtocolException, IOException {
		HttpClient httpClient = createHttpClient();
		HttpPut httpPut = new HttpPut(url);
		httpPut.setEntity(new StringEntity(data));
		HttpResponse response = httpClient.execute(httpPut);
		return processEntity(response.getEntity());
	}

	public static String httpDELETE(String url) throws ClientProtocolException, IOException {
		HttpClient httpClient = createHttpClient();
		HttpResponse response = httpClient.execute(new HttpDelete(url));
		return processEntity(response.getEntity());
	}

	public static Bitmap downloadBitmap(String url) throws ClientProtocolException, IOException {
		HttpClient httpClient = createHttpClient();
		HttpResponse response = httpClient.execute(new HttpDelete(url));
		return processBitmapEntity(response.getEntity());
	}

	public static byte[] downloadResourceAsByteArray(String url) throws ClientProtocolException, IOException {
		HttpClient httpClient = createHttpClient();
		HttpResponse response = httpClient.execute(new HttpDelete(url));
		return processByteArrayEntity(response.getEntity());
	}

	private static HttpClient createHttpClient() {
		HttpClient httpClient = new DefaultHttpClient();
		HttpConnectionParams.setSoTimeout(httpClient.getParams(), 25000);
		return httpClient;
	}

	private static String processEntity(HttpEntity entity) throws IllegalStateException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));
		String line, result = "";
		while ((line = br.readLine()) != null)
			result += line;
		br.close();
		entity.consumeContent();
		return result;
	}

	private static Bitmap processBitmapEntity(HttpEntity entity) throws IOException {
		BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
		Bitmap bm = BitmapFactory.decodeStream(bufHttpEntity.getContent());
		bufHttpEntity.consumeContent();
		return bm;
	}

	private static byte[] processByteArrayEntity(HttpEntity entity) throws IOException {
		BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
		byte[] buffer = Utils.copyStreamToByteArray(bufHttpEntity.getContent());
		bufHttpEntity.consumeContent();
		return buffer;
	}
	
	public static Bitmap fetchImage(String url) {
		if (url == null || "".equals(url.trim()))
			return null;
		Bitmap image = null;
		try {
			image = downloadBitmap(url);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return image;
	}

	public static byte[] fetchByteArray(String url) {
		if (url == null || "".equals(url.trim()) || url.length()<5)
			return null;
		byte[] buffer = null;
		try {
			buffer = downloadResourceAsByteArray(url);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (buffer != null && buffer.length == 0) {
			buffer = null;
		}
		return buffer;
	}
	
	protected static String getString(JSONObject json, String key) {
		String value = "";
		try {
			value = json.getString(key);
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return value;
	}

	protected static int getInt(JSONObject json, String key) {
		int value = -1;
		try {
			value = json.getInt(key);
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return value;
	}
}
